package main

import (
	"github.com/codegangsta/martini"
	"github.com/martini-contrib/binding"
	"github.com/martini-contrib/encoder"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"net/http"
	"time"
//  "fmt"
)

type BlogPost struct {
	Id         bson.ObjectId `form:"-" json:"id" bson:"_id"`
	Title      string        `form:"title" json:"title" bson:"title"`
	Content    string        `form:"content" json:"content" bson:"content"`
	Created_at time.Time     `form:"-" bson:"created_at"`
}

func DB() martini.Handler {
	session, err := mgo.Dial("mongodb://localhost")
	if err != nil {
		panic(err)
	}

	return func(c martini.Context) {
		s := session.Clone()
		c.Map(s.DB("an_demo"))
	}
}

func main() {
	m := martini.Classic()
	m.Use(DB())

	m.Use(func(c martini.Context, w http.ResponseWriter) {
		c.MapTo(encoder.JsonEncoder{}, (*encoder.Encoder)(nil))
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
	})

	m.Get("/posts", func(db *mgo.Database, enc encoder.Encoder) []byte {
		var posts []BlogPost
		db.C("posts").Find(nil).All(&posts)

		dataMap := make(map[string]interface{})
		dataMap["code"] = 0
		dataMap["posts"] = posts
		return encoder.Must(enc.Encode(dataMap))
	})

	m.Get("/posts/:id", func(db *mgo.Database, params martini.Params, enc encoder.Encoder) []byte {
		var blogPost BlogPost
		db.C("posts").Find(bson.M{"_id": bson.ObjectIdHex(params["id"])}).One(&blogPost)

		dataMap := make(map[string]interface{})
		dataMap["code"] = 0
		dataMap["post"] = blogPost
		return encoder.Must(enc.Encode(dataMap))
	})

	m.Post("/posts", binding.Json(BlogPost{}), func(db *mgo.Database, blogPost BlogPost, enc encoder.Encoder) []byte {
		blogPost.Id = bson.NewObjectId()
    db.C("posts").Insert(blogPost)
		return encoder.Must(enc.Encode(map[string]interface{}{"code": 0, "id": blogPost.Id.Hex()}))
	})

	m.Put("/posts/:id", binding.Json(BlogPost{}), func(db *mgo.Database, params martini.Params, enc encoder.Encoder, blogPost BlogPost) []byte {
		update_bson := bson.M{"title": blogPost.Title, "content": blogPost.Content}
		select_bson := bson.M{"_id": bson.ObjectIdHex(params["id"])}
		db.C("posts").Update(select_bson, update_bson)
		data := map[string]interface{}{"code": 0}
		return encoder.Must(enc.Encode(data))
	})

	m.Delete("/posts/:id", func(db *mgo.Database, params martini.Params, enc encoder.Encoder) []byte {
		select_bson := bson.M{"_id": bson.ObjectIdHex(params["id"])}
		db.C("posts").Remove(select_bson)
		return encoder.Must(enc.Encode(map[string]interface{}{"code": 0}))
	})

	m.Run()
}
